package com.onvifdemo;

import be.teletask.onvif.DiscoveryManager;
import be.teletask.onvif.OnvifManager;
import be.teletask.onvif.listeners.*;
import be.teletask.onvif.models.*;
import com.alibaba.fastjson.JSONObject;
import com.onvifdemo.dto.DeviceInfoDTO;
import com.onvifdemo.listener.MyDeviceInformationListener;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import static org.apache.commons.lang3.SystemUtils.getHostName;


@SpringBootApplication
public class OnvifdemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext cac = SpringApplication.run(OnvifdemoApplication.class, args);
        // 发现设备
        discoveryManager().thenAccept(devices -> {
            // 处理onvifProfile
            System.out.println("\n发现设备devices 数据：" + JSONObject.toJSONString(devices));
        }).exceptionally(ex -> {
            // 处理异常
            return null;
        });

        DeviceInfoDTO deviceInfo = new DeviceInfoDTO();
        deviceInfo.setIp("192.168.1.11");
        deviceInfo.setAuthAccount("admin");
        deviceInfo.setAuthPassword("csr.123456789");

        getProfile(deviceInfo).thenAccept(onvifProfile -> {
            // 处理onvifProfile
            System.out.println("\ngetProfile数据：" + JSONObject.toJSONString(onvifProfile));
        }).exceptionally(ex -> {
            // 处理异常
            return null;
        });
    }

    /**
     * 测试用
     * @param deviceInfo
     * @return
     */
    private static CompletableFuture<GetAudioDecoderConfigurationOptions> getTest(DeviceInfoDTO deviceInfo) {
        CompletableFuture<GetAudioDecoderConfigurationOptions> future = new CompletableFuture<>();
        MyDeviceInformationListener listener = new MyDeviceInformationListener();
        OnvifManager onvifManager = new OnvifManager(listener);
        OnvifDevice device = new OnvifDevice(deviceInfo.getIp(), deviceInfo.getAuthAccount(), deviceInfo.getAuthPassword());
        onvifManager.getMediaProfiles(device, new OnvifMediaProfilesListener() {
            @Override
            public void onMediaProfilesReceived(OnvifDevice device,
                                                List<OnvifMediaProfile> mediaProfiles) {
                if (!mediaProfiles.isEmpty()) {
                    System.out.println("\nMediaProfiles数据：" + JSONObject.toJSONString(mediaProfiles));
                    onvifManager.GetAudioDecoderConfigurationOptions(device, mediaProfiles.get(0), new GetAudioDecoderConfigurationOptionsListener() {
                        @Override
                        public void onReceived(OnvifDevice onvifDevice, GetAudioDecoderConfigurationOptions getAudioDecoderConfigurationOptions) {
                            future.complete(getAudioDecoderConfigurationOptions);
                        }

                        @Override
                        public void onError(OnvifDevice onvifDevice, int i, String s) {
                            future.completeExceptionally(new RuntimeException(s));
                        }
                    });
                }else {
                    future.completeExceptionally(new RuntimeException("No media profiles found"));
                }
            }

            @Override
            public void onError(OnvifDevice onvifDevice, int i, String s) {
                future.completeExceptionally(new RuntimeException(s));
            }
        });

        return future;
    }

    /**
     * 发现设备
     * @return
     */
    public static CompletableFuture<List<Device>> discoveryManager() {
        CompletableFuture<List<Device>> future = new CompletableFuture<>();
        DiscoveryManager manager = new DiscoveryManager();
        manager.setDiscoveryTimeout(10000);
        manager.discover(new DiscoveryListener() {
            @Override
            public void onDiscoveryStarted() {
                System.out.println("Discovery started");
            }

            @Override
            public void onDevicesFound(List<Device> devices) {
                System.out.println("Devices found: " + JSONObject.toJSONString(devices));
                future.complete(devices);
            }
        });

        return future;
    }

    /**
     * 设备信息
     * @return
     */
    private static CompletableFuture<OnvifDeviceInformation> getDeviceInformation(DeviceInfoDTO deviceInfo) {
        CompletableFuture<OnvifDeviceInformation> future = new CompletableFuture<>();
        MyDeviceInformationListener listener = new MyDeviceInformationListener();
        OnvifManager onvifManager = new OnvifManager(listener);
        OnvifDevice device = new OnvifDevice(deviceInfo.getIp(), deviceInfo.getAuthAccount(), deviceInfo.getAuthPassword());

        onvifManager.getDeviceInformation(device, new OnvifDeviceInformationListener() {
            @Override
            public void onDeviceInformationReceived(OnvifDevice device, OnvifDeviceInformation deviceInformation) {
                future.complete(deviceInformation);
            }

            @Override
            public void onError(OnvifDevice onvifDevice, int i, String s) {
                future.completeExceptionally(new RuntimeException(s));
            }
        });

        return future;
    }

    /**
     * 获取token
     * @return
     */
    private static CompletableFuture<List<OnvifMediaProfile>> getMediaProfiles(DeviceInfoDTO deviceInfo) {
        CompletableFuture<List<OnvifMediaProfile>> future = new CompletableFuture<>();
        MyDeviceInformationListener listener = new MyDeviceInformationListener();
        OnvifManager onvifManager = new OnvifManager(listener);
        OnvifDevice device = new OnvifDevice(deviceInfo.getIp(), deviceInfo.getAuthAccount(), deviceInfo.getAuthPassword());

        onvifManager.getMediaProfiles(device, new OnvifMediaProfilesListener() {
            @Override
            public void onMediaProfilesReceived(OnvifDevice device, List<OnvifMediaProfile> mediaProfiles) {
                future.complete(mediaProfiles);
            }

            @Override
            public void onError(OnvifDevice onvifDevice, int i, String s) {
                future.completeExceptionally(new RuntimeException(s));
            }
        });
        return future;
    }

    /**
     * 获取云台能力
     * @param deviceInfo
     * @return
     */
    private static CompletableFuture<OnvifProfile> getProfile(DeviceInfoDTO deviceInfo) {
        CompletableFuture<OnvifProfile> future = new CompletableFuture<>();
        MyDeviceInformationListener listener = new MyDeviceInformationListener();
        OnvifManager onvifManager = new OnvifManager(listener);
        OnvifDevice device = new OnvifDevice(deviceInfo.getIp(), deviceInfo.getAuthAccount(), deviceInfo.getAuthPassword());
        onvifManager.getMediaProfiles(device, new OnvifMediaProfilesListener() {
            @Override
            public void onMediaProfilesReceived(OnvifDevice device,
                                                List<OnvifMediaProfile> mediaProfiles) {
                if (!mediaProfiles.isEmpty()) {
                    onvifManager.getProfile(device, mediaProfiles.get(0), new OnvifProfileListener() {
                        @Override
                        public void onProfileReceived(OnvifDevice onvifDevice, OnvifProfile onvifProfile) {
                            future.complete(onvifProfile);
                        }

                        @Override
                        public void onError(OnvifDevice onvifDevice, int i, String s) {
                            future.completeExceptionally(new RuntimeException(s));
                        }
                    });
                }else {
                    future.completeExceptionally(new RuntimeException("No media profiles found"));
                }
            }

            @Override
            public void onError(OnvifDevice onvifDevice, int i, String s) {
                future.completeExceptionally(new RuntimeException(s));
            }
        });

        return future;
    }

    /**
     * 获取RTSP流地址
     * @param profile
     * @return
     */
    private static CompletableFuture<String> getMediaStreamURI(DeviceInfoDTO deviceInfo) {
        CompletableFuture<String> future = new CompletableFuture<>();
        MyDeviceInformationListener listener = new MyDeviceInformationListener();
        OnvifManager onvifManager = new OnvifManager(listener);
        OnvifDevice device = new OnvifDevice(deviceInfo.getIp(), deviceInfo.getAuthAccount(), deviceInfo.getAuthPassword());
        onvifManager.getMediaProfiles(device, new OnvifMediaProfilesListener() {
            @Override
            public void onMediaProfilesReceived(OnvifDevice device,
                                                List<OnvifMediaProfile> mediaProfiles) {
                if (!mediaProfiles.isEmpty()) {
                    onvifManager.getMediaStreamURI(device, mediaProfiles.get(0), new OnvifMediaStreamURIListener() {
                        @Override
                        public void onMediaStreamURIReceived(OnvifDevice device, OnvifMediaProfile profile, String uri) {
                            future.complete(uri);
                        }

                        @Override
                        public void onError(OnvifDevice onvifDevice, int i, String s) {
                            future.completeExceptionally(new RuntimeException(s));
                        }
                    });
                }else {
                    future.completeExceptionally(new RuntimeException("No media profiles found"));
                }
            }

            @Override
            public void onError(OnvifDevice onvifDevice, int i, String s) {
                future.completeExceptionally(new RuntimeException(s));
            }
        });

        return future;
    }

    /**
     * 监控HTTP地址
     * @param profile
     * @return
     */
    private static CompletableFuture<String> getSnapshotURI(DeviceInfoDTO deviceInfo) {
        CompletableFuture<String> future = new CompletableFuture<>();
        MyDeviceInformationListener listener = new MyDeviceInformationListener();
        OnvifManager onvifManager = new OnvifManager(listener);
        OnvifDevice device = new OnvifDevice(deviceInfo.getIp(), deviceInfo.getAuthAccount(), deviceInfo.getAuthPassword());

        onvifManager.getMediaProfiles(device, new OnvifMediaProfilesListener() {
            @Override
            public void onMediaProfilesReceived(OnvifDevice device,
                                                List<OnvifMediaProfile> mediaProfiles) {
                if (!mediaProfiles.isEmpty()) {
                    onvifManager.getSnapshotURI(device, mediaProfiles.get(0), new OnvifSnapshotURIListener() {
                        @Override
                        public void onSnapshotURIReceived(OnvifDevice onvifDevice, OnvifMediaProfile onvifMediaProfile, String uri) {
                            future.complete(uri);
                        }

                        @Override
                        public void onError(OnvifDevice onvifDevice, int i, String s) {
                            future.completeExceptionally(new RuntimeException(s));
                        }
                    });
                }else {
                        future.completeExceptionally(new RuntimeException("No media profiles found"));
                    }
                }

                @Override
                public void onError(OnvifDevice onvifDevice, int i, String s) {
                    future.completeExceptionally(new RuntimeException(s));
                }
            });

        return future;
    }

    /**
     * 持续移动/缩放
     * @param profile
     * @return
     */
    private static CompletableFuture<String> continuousMove(DeviceInfoDTO deviceInfo) {
        CompletableFuture<String> future = new CompletableFuture<>();
        MyDeviceInformationListener listener = new MyDeviceInformationListener();
        OnvifManager onvifManager = new OnvifManager(listener);
        OnvifDevice device = new OnvifDevice(deviceInfo.getIp(), deviceInfo.getAuthAccount(), deviceInfo.getAuthPassword());
        onvifManager.getMediaProfiles(device, new OnvifMediaProfilesListener() {
            @Override
            public void onMediaProfilesReceived(OnvifDevice device,
                                                List<OnvifMediaProfile> mediaProfiles) {
                if (!mediaProfiles.isEmpty()) {
                    onvifManager.continuousMove(device, mediaProfiles.get(0), 0f, 0f, 0f);
                }else {
                    future.completeExceptionally(new RuntimeException("No media profiles found"));
                }
            }

            @Override
            public void onError(OnvifDevice onvifDevice, int i, String s) {
                future.completeExceptionally(new RuntimeException(s));
            }
        });

        return future;
    }

    /**
     * 相对移动/缩放
     * @param profile
     * @return
     */
    private static CompletableFuture<String> relativeMove(DeviceInfoDTO deviceInfo) {
        CompletableFuture<String> future = new CompletableFuture<>();
        MyDeviceInformationListener listener = new MyDeviceInformationListener();
        OnvifManager onvifManager = new OnvifManager(listener);
        OnvifDevice device = new OnvifDevice(deviceInfo.getIp(), deviceInfo.getAuthAccount(), deviceInfo.getAuthPassword());
        onvifManager.getMediaProfiles(device, new OnvifMediaProfilesListener() {
            @Override
            public void onMediaProfilesReceived(OnvifDevice device,
                                                List<OnvifMediaProfile> mediaProfiles) {
                if (!mediaProfiles.isEmpty()) {
                    onvifManager.relativeMove(device, mediaProfiles.get(0), 0.6f, 0f, 0f);
                }else {
                    future.completeExceptionally(new RuntimeException("No media profiles found"));
                }
            }

            @Override
            public void onError(OnvifDevice onvifDevice, int i, String s) {
                future.completeExceptionally(new RuntimeException(s));
            }
        });

        return future;
    }

    /**
     * 获取service和设备信息
     * @return
     */
    private static CompletableFuture<OnvifProfile> DiscoveryManager(DeviceInfoDTO deviceInfo) {
        CompletableFuture<OnvifProfile> future = new CompletableFuture<>();
        MyDeviceInformationListener listener = new MyDeviceInformationListener();
        OnvifManager onvifManager = new OnvifManager(listener);
        OnvifDevice device = new OnvifDevice(deviceInfo.getIp(), deviceInfo.getAuthAccount(), deviceInfo.getAuthPassword());
//      获取services
//        onvifManager.getServices(device, new OnvifServicesListener() {
//            @Override
//            public void onServicesReceived(OnvifDevice onvifDevice, OnvifServices services) {
//                System.out.println("services信息如下：\n" + services.getDevicePath() + "\n" + services.getMediaPath()
//                        + "\n" + services.getServicesPath() + "\n" + services.getPtzPath());
//
//            }
//        });

        onvifManager.getMediaProfiles(device, new OnvifMediaProfilesListener() {
            @Override
            public void onMediaProfilesReceived(OnvifDevice device,
                                                List<OnvifMediaProfile> mediaProfiles) {
                if (!mediaProfiles.isEmpty()) {
                    int size = mediaProfiles.size();
                    System.out.println("\nMediaProfiles数据长度如下：" + size);
                    System.out.println("\nMediaProfiles数据：" + JSONObject.toJSONString(mediaProfiles));
//                onvifManager.absoluteMove(device, mediaProfiles.get(0), 0.1f, 0.59f, 0.2f);
//                onvifManager.relativeMove(device, mediaProfiles.get(0), 1f, 0f, 0f);
//                onvifManager.focusMove(device, mediaProfiles.get(0), Float.valueOf(0), Float.valueOf(0.5F));
//                onvifManager.getMediaStreamURI(device, mediaProfiles.get(0), new OnvifMediaStreamURIListener() {
//                    @Override
//                    public void onMediaStreamURIReceived(OnvifDevice device,
//                                                         OnvifMediaProfile profile, String uri) {
//                        System.out.println("\nrtsp uri数据如下：" + uri);
//                    }
//                });

                    onvifManager.getProfile(device, mediaProfiles.get(0), new OnvifProfileListener() {

                        @Override
                        public void onProfileReceived(OnvifDevice onvifDevice, OnvifProfile onvifProfile) {
                            future.complete(onvifProfile);
                        }

                        @Override
                        public void onError(OnvifDevice onvifDevice, int i, String s) {
                            future.completeExceptionally(new RuntimeException(s));
                        }
                    });
                } else {
                    future.completeExceptionally(new RuntimeException("No media profiles found"));
                }

//                onvifManager.getSnapshotURI(device, mediaProfiles.get(0), new OnvifSnapshotURIListener() {
//                    @Override
//                    public void onSnapshotURIReceived(OnvifDevice onvifDevice, OnvifMediaProfile onvifMediaProfile, String uri) {
//                        System.out.println("\nuri数据如下：" + uri);
//                    }
//                });
            }

            @Override
            public void onError(OnvifDevice onvifDevice, int i, String s) {
                future.completeExceptionally(new RuntimeException(s));
            }
        });
        return future;
    }

    public static void saveFile(String urls, String username, String password) throws IOException {
        // 账号密码base64编码(海康)
        String userPassword = username + ":" + password;
        String encoding = Base64.encodeBase64String(userPassword.getBytes());
        // 构造URL
        URL url = new URL(urls);
        // 打开连接
        URLConnection con = url.openConnection();
        con.setRequestProperty("Authorization", "Basic " + encoding);
        // 格式化时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HHmmssSSS");
        String format = simpleDateFormat.format(new Date());
        // 输出的文件流
        String path = "D:/a";
        File pathFile = new File(path);
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }
        String filename = path + "/" + format + ".jpg";
        File file = new File(filename);
        // 1k的缓冲数据
        byte[] bs = new byte[1024];
        // 阅读到的数据长度
        int len;
        // 获取输入流
        InputStream inputStream = con.getInputStream();
        // 开始读取
        FileOutputStream outputStream = new FileOutputStream(file, true);
        while ((len = inputStream.read(bs)) != -1) {
            outputStream.write(bs, 0, len);
        }
        inputStream.close();
        outputStream.close();
    }
}
